package com.disruptor.base;

import java.nio.ByteBuffer;

import com.lmax.disruptor.EventTranslatorOneArg;
import com.lmax.disruptor.RingBuffer;

//事件生产者,事件发布
public class LongEventProducer {

    private final RingBuffer<LongEvent> ringBuffer;

    public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }

    /**
     * 发布事件,,每调用一次就发布一次事件,参数传递给消费者
     * 发布事件最少需要两步：获取下一个事件槽并发布事件（发布事件的时候要使用try/finnally保证事件一定会被发布）。
     * 如果我们使用RingBuffer.next()获取一个事件槽，那么一定要发布对应的事件。
     * 如果不能发布事件，那么就会引起Disruptor状态的混乱。
     * 尤其是在多个事件生产者的情况下会导致事件消费者失速，从而不得不重启应用才能会恢复
     */
    public void onData(ByteBuffer buf) {
        //1.可以把ringBuffer看做一个事件队列，那么next就是得到下面一个事件槽
        long sequence = ringBuffer.next();
        try {
            //2.用上面的索引取出一个空的事件用于填充（获取该序号对应的事件对象）
            LongEvent event = ringBuffer.get(sequence);
            //3.获取要通过事件传递的业务数据
            event.setValue(buf.getLong(0));
        } finally {
            //4.发布事件
            //注意，最后的 ringBuffer.publish 方法必须包含在 finally 中以确保必须得到调用；
            //如果某个请求的 sequence 未被提交，将会堵塞后续的发布操作或者其它的 producer。ingBuffer.publish(sequence);
        }
    }
}
